home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / misc / amag / 9301b.lha / Devices (Folge 3) / Terminal.c < prev    next >
C/C++ Source or Header  |  1992-04-18  |  16KB  |  503 lines

  1. /* Terminal.c
  2.  
  3.    Autor: E.G. Meyzis, Mai 1992
  4.  
  5.    Compile Instr. fuer DICE:                   execute cterm
  6.    dcc Terminal.c -c -o t:Terminal.o
  7.  
  8.    Link Instr. fuer DICE:                      execute lterm
  9.    dlink dlib:c.o t:Terminal.o dlib:c.lib+
  10.    dlib:amigas20.lib dlib:auto.lib dlib:x.o -o Terminal
  11. */
  12.  
  13. #include <Devices/Serial.h>
  14. #include <Dos/Dos.h>
  15. #include <Dos/DosExtens.h>
  16. #include <Exec/Exec.h>
  17. #include <Intuition/Intuition.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20.  
  21. /* +++++++++  Definitionen  ++++++++++++
  22. */
  23. #define TRUE  1   /* um mit dem Datentyp BOOL zu arbeiten */
  24. #define FALSE 0
  25.  
  26.       /* zwei Definitionen fuer DOS-Fenster */
  27.  
  28. #define TxTitle "CON:0/0/500/100/ Terminal-Send "
  29. #define RxTitle "CON:0/101/500/100/ Terminal-Receive "
  30.  
  31.       /* Texte zur Info bei Text-Senden/Empfangen */
  32.  
  33. #define Senden   "\nSende Textdatei\n\n"
  34. #define Empfang  "\nwarte auf Textdatei\n\n"
  35. #define Beendet  "\nÜbertragung beendet\n\n"
  36.  
  37. #define Unit0     0      /* eingebaute ser. Schnittstelle */
  38. #define PLaenge 512      /* Pufferlaenge Datemuebertrag.  */
  39.  
  40. struct GetBlock             /* nur in GetWinPtr verwendet */
  41.          {
  42.           struct StandardPacket stdPkt;
  43.           struct InfoData       info;
  44.          };
  45.  
  46. /* +++++++++  Datentypen  ++++++++++++
  47. */
  48. typedef char                BOOL;
  49. typedef char                *CharPtr;
  50. typedef struct IOExtSer     *IOExtSerPtr;
  51. typedef struct FileHandle   *FileHandleBPtr;      /* BPTR */
  52. typedef struct FileHandle   *FileHandlePtr;    /* Adresse */
  53. typedef struct Window       *WindowPtr;
  54. typedef struct GetBlock     *GetBlockPtr;
  55. typedef struct MessagePort  *MsgPortPtr;
  56. typedef struct IntuiMessage *IntuiMessagePtr;
  57.  
  58.  
  59. APTR GetSysBase();    /* Adr ExecBase aus Adresse 4 holen */
  60.  
  61. void GetWinPointer (FileHandleBPtr *winHdl,
  62.                     WindowPtr      *winPtr);
  63. void MakeWindow(CharPtr        namePtr,
  64.                 WindowPtr      *winPtr,
  65.                 FileHandleBPtr *fileHdl);
  66. BOOL WindowsAngelegt();
  67.  
  68. void SetBaudRate(IOExtSerPtr serPtr);
  69. BOOL InitSerialDev(IOExtSerPtr serPtr, int cmnd);
  70. BOOL SerialVorbereitet();
  71. void SetTermChars(IOExtSerPtr serPtr);
  72. void FlushSerialDevice();
  73.  
  74. void SendeTextDatei(IOExtSerPtr txReqPtr);
  75. void EmpfangeTextDatei(IOExtSerPtr rxReqPtr);
  76.  
  77. void TerminalLoop();
  78. void Aufraeumen();
  79.  
  80. /* +++++++++  globale Variablen  ++++++++++++
  81. */
  82. struct ExecBase *execBasePtr;
  83.  
  84. /*
  85.                Doppelt ausgelegte Datenstrukturen
  86.  
  87.                 Sendeteil:         Empfangsteil:
  88. */
  89.                 /* Device zweimal oeffnen */
  90. struct IOExtSer txRequest,         rxRequest;
  91.  
  92.                 /* jedem Device seinen Puffer */
  93. char            rxPuffer[PLaenge], txPuffer[PLaenge];
  94.  
  95.                 /* getrennte Fenster fuer Ein-/Ausgaben */
  96. FileHandleBPtr  txWin,             rxWin;
  97. WindowPtr       txWinPtr,          rxWinPtr;
  98.  
  99.  
  100.  
  101. APTR GetSysBase() /* Adr ExecBase aus Adresse 4 holen */
  102. {
  103.  long *systemBasis;
  104.  
  105.  systemBasis = (APTR)4;
  106.  return (APTR)*systemBasis;
  107. }
  108.  
  109.  
  110. /* Mit Dos.Open geoeffnete Fenster liefern nur einen Handle
  111.    und leider nicht den WindowPtr; deshalb:
  112. */
  113. void GetWinPointer (FileHandleBPtr *winHdl,
  114.                     WindowPtr      *winPtr)
  115. {
  116.  MsgPortPtr  portPtr;
  117.  GetBlockPtr pktPtr;
  118.  
  119.  FileHandlePtr wHdlPtr;
  120.  
  121.  *winPtr = NULL;                   /* negatives Vorurteil */
  122.  if (IsInteractive(*winHdl))        /* Fenster vorhanden? */
  123.    {
  124.     wHdlPtr = (APTR)((long)*winHdl) << 2;  /* BPTR -> Adr */
  125.     if (portPtr = (MsgPortPtr)CreateMsgPort())
  126.       {
  127.        /* Speicher fuer Dos.Packet anfordern*/
  128.  
  129.        pktPtr=(GetBlockPtr)AllocMem(sizeof(struct GetBlock),
  130.                                     MEMF_CLEAR|MEMF_PUBLIC);
  131.        if (pktPtr)           /* Dos.Packet initialisieren */
  132.          {
  133.           pktPtr->stdPkt.sp_Pkt.dp_Link =
  134.                                      &pktPtr->stdPkt.sp_Msg;
  135.           pktPtr->stdPkt.sp_Pkt.dp_Port = portPtr;
  136.           pktPtr->stdPkt.sp_Pkt.dp_Type = ACTION_DISK_INFO;
  137.           pktPtr->stdPkt.sp_Pkt.dp_Arg1 = &pktPtr->info >>2;
  138.           pktPtr->stdPkt.sp_Msg.mn_Node.ln_Name =
  139.                                      &pktPtr->stdPkt.sp_Pkt;
  140.           pktPtr->stdPkt.sp_Msg.mn_Node.ln_Type= NT_MESSAGE;
  141.           pktPtr->stdPkt.sp_Msg.mn_Length =
  142.                                      sizeof(struct Message);
  143.  
  144.           PutMsg(wHdlPtr->fh_Type, pktPtr);/*und absenden */
  145.           do
  146.             WaitPort(portPtr);     /* auf Antwort von Dos */
  147.           while (APTR)GetMsg(portPtr) != pktPtr;
  148.  
  149.           if (pktPtr->stdPkt.sp_Pkt.dp_Res1)/* Antwort ok */
  150.              *winPtr = (APTR)pktPtr->info.id_VolumeNode;
  151.  
  152.            DeleteMsgPort(portPtr);
  153.            FreeMem(pktPtr, sizeof(struct GetBlock));
  154.          }
  155.        else
  156.          DeleteMsgPort(portPtr);
  157.       }
  158.  
  159.    } /* Interactive */
  160. }
  161.  
  162.  
  163. /* Dos.Fenster anlegen und WindowPtr holen */
  164.  
  165. void MakeWindow(CharPtr        namePtr,
  166.                 WindowPtr      *winPtr,
  167.                 FileHandleBPtr *fileHdl)
  168.  
  169. {
  170.   *fileHdl = (FileHandleBPtr)Open(namePtr, MODE_NEWFILE);
  171.   if (*fileHdl)
  172.     GetWinPointer(&(*fileHdl), &(*winPtr));
  173. }
  174.  
  175.  
  176. /* Beide Terminal-Fenster anlegen und bei Fehlschlag
  177.    Ressourcen freigeben.
  178. */
  179. BOOL WindowsAngelegt()
  180. {
  181.   BOOL angelegt;
  182.  
  183.   angelegt = FALSE;         /* zunaechst keines vorhanden */
  184.  
  185.   MakeWindow(TxTitle, &txWinPtr, &txWin);/* Sende-Fenster */
  186.   if (txWinPtr)
  187.     {
  188.      angelegt = TRUE;
  189.  
  190.      /* um Tastatureingaben durch Intuition abzufangen */
  191.  
  192.      ModifyIDCMP(txWinPtr, IDCMP_RAWKEY|IDCMP_VANILLAKEY);
  193.  
  194.      MakeWindow(RxTitle, &rxWinPtr, &rxWin);/*Empf.-Fenst */
  195.      if (rxWinPtr = NULL)
  196.        {
  197.         angelegt = FALSE;        /* Sendefenster aufgeben */
  198.         Close(txWin);
  199.         txWin = NULL;
  200.        }
  201.     }
  202.   else                    /* WindowPtr nicht zu ermitteln */
  203.     if (txWin)
  204.        Close(txWin);                /* deshalb schliessen */
  205.   return angelegt;
  206. }
  207.  
  208. void SetBaudRate(IOExtSerPtr serPtr)
  209. {
  210.   serPtr->io_Baud = 9600;
  211.   serPtr->IOSer.io_Command = SDCMD_SETPARAMS;
  212.   DoIO(serPtr);
  213.               /* io_Command nach dem Aufruf zuruecksetzen */
  214. }
  215.  
  216. void SetTermChars(IOExtSerPtr serPtr)
  217. {
  218.   serPtr->IOSer.io_Command = SDCMD_SETPARAMS;
  219.   serPtr->io_SerFlags |= SERF_EOFMODE;
  220.   serPtr->io_TermArray.TermArray0 = 0x1C040303;
  221.                                    /* EOF-EOT-ETX-ETX */
  222.   serPtr->io_TermArray.TermArray1 = 0x03030303;
  223.                                    /* RTX-... */
  224.   DoIO(serPtr);
  225.               /* io_Command nach dem Aufruf zuruecksetzen */
  226. }
  227.  
  228.  
  229. /* Device-Struktur initialisieren und Device oeffnen */
  230.  
  231. BOOL InitSerialDev(IOExtSerPtr serPtr, int cmnd)
  232. {
  233.   MsgPortPtr  portPtr;
  234.   BOOL        erfolg;
  235.  
  236.   erfolg = FALSE;
  237.   portPtr = (MsgPortPtr)CreateMsgPort();   /* fuer Device */
  238.   if (portPtr)
  239.     {
  240.      serPtr->io_SerFlags = SERF_SHARED; /* Mehrfachutzung */
  241.      serPtr->IOSer.io_Length = 1;/* 1 Byte lesen/schreib. */
  242.      serPtr->IOSer.io_Message.mn_ReplyPort = portPtr;
  243.  
  244.      OpenDevice(SERIALNAME, Unit0, serPtr, 0);
  245.      if (serPtr->IOSer.io_Error != IOERR_OPENFAIL)
  246.        {
  247.         erfolg = TRUE;
  248.         SetBaudRate(serPtr);
  249.         serPtr->IOSer.io_Command = cmnd;/* CMD_WRITE/READ */
  250.        }
  251.       else                     /* Device nicht zu oeffnen */
  252.        {
  253.         DeleteMsgPort
  254.                     (serPtr->IOSer.io_Message.mn_ReplyPort);
  255.         serPtr->IOSer.io_Message.mn_ReplyPort = NULL;
  256.        }
  257.     }
  258.   return erfolg;
  259. }
  260.  
  261.  
  262. BOOL SerialVorbereitet() /* getrennte Devices als  Sende- */
  263. {                        /* Empfangskanal oeffnen */
  264.   BOOL vorbereitet;
  265.  
  266.   if (InitSerialDev(&txRequest, CMD_WRITE)) /* Sendekanal */
  267.     {
  268.      vorbereitet = TRUE;
  269.      txRequest.IOSer.io_Data=txPuffer;/*f. Dateiuebertrag.*/
  270.  
  271.      if (InitSerialDev(&rxRequest, CMD_READ))/*Empf.-Kanal*/
  272.        {
  273.         rxRequest.IOSer.io_Data = rxPuffer; /* ext. Puffer*/
  274.        }
  275.      else                /* kein Empfangskanal zu oeffnen */
  276.        {
  277.         vorbereitet = FALSE;
  278.         DeleteMsgPort
  279.                   (txRequest.IOSer.io_Message.mn_ReplyPort);
  280.         txRequest.IOSer.io_Message.mn_ReplyPort = NULL;
  281.        }
  282.     }
  283.   else/*kein Kanal zu oeffnen; Device evtl exklusiv belegt*/
  284.     vorbereitet = FALSE;
  285.  
  286.   return vorbereitet;
  287. }
  288.  
  289. void SendeTextDatei(IOExtSerPtr txReqPtr)
  290. {
  291.   FileHandleBPtr txDateiHdl;
  292.   long           gelesen,
  293.                  geschrieben;
  294.  
  295.   geschrieben = FPuts(txWin, Senden);        /* Info-Text */
  296.   SetTermChars(txReqPtr);     /* um Dateiende zu erkennen */
  297.   txReqPtr->IOSer.io_Command = CMD_WRITE;
  298.   txDateiHdl = (FileHandleBPtr       ) /* exemplar. Datei */
  299.                 Open("S:StartUp-Sequence", MODE_OLDFILE);
  300.   if (txDateiHdl)            /* Datei zum Lesen geoeffnet */
  301.     {
  302.      for(;;)                            /* Endlosschleife */
  303.        {
  304.         gelesen =                     /* Datenblock lesen */
  305.            FRead(txDateiHdl, txPuffer, 1, sizeof(txPuffer));
  306.         if (gelesen)                       /* Byte-Anzahl */
  307.           {
  308.            txReqPtr->IOSer.io_Length = gelesen;
  309.            DoIO(txReqPtr);                  /* abschicken */
  310.            geschrieben = Write(txWin, ".", 1);/* nur Info */
  311.           }
  312.         else               /* nichts (mehr) gelesen, also */
  313.           break;                 /* raus aus der Schleife */
  314.  
  315.         if (txReqPtr->IOSer.io_Error)  /* bei Sendefehler */
  316.            break;                   /* Schleife verlassen */
  317.        }
  318.      Close(txDateiHdl);
  319.     }
  320.   geschrieben = FPuts(txWin, Beendet);        /* nur Info */
  321. }
  322.  
  323. void EmpfangeTextDatei(IOExtSerPtr rxReqPtr)
  324. {
  325.   FileHandleBPtr  rxDatei;
  326.   long            geschrieben;
  327.  
  328.   AbortIO(rxReqPtr); /* den einzigen Request aus dem Emp- */
  329.   WaitIO(rxReqPtr);            /* fangskanal zurueckholen */
  330.  
  331.   geschrieben = FPuts(rxWin, Empfang);        /* zur Info */
  332.  
  333.   SetTermChars(rxReqPtr);  /* Dateiende automat. erkennen */
  334.  
  335.   rxReqPtr->IOSer.io_Length = 1;/*zunaechst nur 1 Zeichen */
  336.  
  337.   rxDatei = (FileHandleBPtr)   /* dorthin Daten schreiben */
  338.             Open("RAM:Ser.tst", MODE_NEWFILE);
  339.   if (rxDatei)                         /* Datei geoeffnet */
  340.     {
  341.      for(;;)         /* schoen-gefaehrliche Dauerschleife */
  342.        {
  343.         rxReqPtr->IOSer.io_Command = CMD_READ;
  344.         DoIO(rxReqPtr);                /* Zeichen abholen */
  345.         if (rxReqPtr->IOSer.io_Actual)      /* Zeichen da */
  346.           {
  347.            geschrieben =            /* in Datei schreiben */
  348.                          FWrite(rxDatei, rxPuffer, 1,
  349.                          rxReqPtr->IOSer.io_Actual);
  350.            geschrieben = Write(rxWin, ".", 1);    /* Info */
  351.           }
  352.         else                            /* nichts gelesen */
  353.           break;                     /* deshalb abbrechen */
  354.  
  355.         rxReqPtr->IOSer.io_Command = SDCMD_QUERY;
  356.         DoIO(rxReqPtr); /* Anz. Zeichen im dev-int. Puff.?*/
  357.         if (rxReqPtr->IOSer.io_Actual == 0)   /* keine da */
  358.           break;                     /* raus aus Schleife */
  359.         else /* Leselaenge auf Anzahl vorhandener Zeichen */
  360.           rxReqPtr->IOSer.io_Length =
  361.                                rxReqPtr->IOSer.io_Actual;
  362.         } /* for */
  363.       Close(rxDatei);
  364.     }
  365.   geschrieben = FPuts(rxWin, Beendet);
  366. }
  367.  
  368. void TerminalLoop()           /* Hauptschleife  des Prog. */
  369. {
  370.   IntuiMessagePtr inMsgPtr;  /* fuer IDCMP-Nachr. aus dem */
  371.   long            klasse,                 /* Sendefenster */
  372.                   done,
  373.                   txSig, /*aus UserPort des Sendefensters */
  374.                   rxSig,  /* aus Empfangs-Device-Struktur */
  375.                   erwartSig, /* Kombination txSig | rxSig */
  376.                   erhaltSig;       /* angekommene Signale */
  377.   int             raw;             /* fuer Tastatur-Codes */
  378.  
  379.   txSig = 1 << txWinPtr->UserPort->mp_SigBit;
  380.   rxSig = 1 <<
  381.          rxRequest.IOSer.io_Message.mn_ReplyPort->mp_SigBit;
  382.   erwartSig = txSig | rxSig;
  383.  
  384.   SendIO(&(rxRequest));  /* async. aufs 1. Zeichen warten */
  385.   for(;;)
  386.     {
  387.      erhaltSig = Wait(erwartSig);  /* Tastendruck/Empfang */
  388.      if (txSig & erhaltSig) /*Taste im Sendefenster gedr. */
  389.        {
  390.         inMsgPtr = (IntuiMessagePtr)      /* Msg. abholen */
  391.                    GetMsg(txWinPtr->UserPort);
  392.  
  393.         klasse = inMsgPtr->Class;   /* copy Msg teilweise */
  394.         raw    = inMsgPtr->Code;
  395.  
  396.         ReplyMsg(inMsgPtr);            /* Msg beantworten */
  397.  
  398.         if (IDCMP_VANILLAKEY & klasse)   /* ASCII-Zeichen */
  399.           {
  400.            txPuffer[0] = raw;  /* Zeichen in Sende-Puffer */
  401.            if (txPuffer[0] != 033) /* nicht ESC gedrueckt */
  402.              {
  403.               done = Write(txWin, txPuffer, 1);   /* Echo */
  404.               DoIO(&txRequest);         /* Zeichen senden */
  405.              }
  406.            else                          /* ESC gedrueckt */
  407.              break;                 /* Programm abbrechen */
  408.           }
  409.        else
  410.          if (IDCMP_RAWKEY & klasse) /* z.B. F1 - F10 gedr.*/
  411.            {
  412.             if ((raw >= 80) && (raw <= 89))
  413.               {
  414.               /* Funktionstasten auswerten F1 - F10 */
  415.                if (raw == 80)                       /* F1 */
  416.                  {
  417.                 /* 5. Erweiterung
  418.                    Aufruf SendeTextDatei(txRequest);
  419.                    aus Listing 3-5 hier einfuegen
  420.                 */
  421.  
  422.                 SendeTextDatei(&txRequest);
  423.                  }
  424.                 else
  425.                   if (raw == 81)                    /* F2 */
  426.  
  427.                   /* 6. Erweiterung
  428.                      Aufruf EmpfangeTextDatei(rxRequest);
  429.                      aus Listing 3-6 hier einfuegen
  430.                   */
  431.  
  432.                     EmpfangeTextDatei(&rxRequest);
  433.               } /* raw >= 80*/
  434.            } /* IDCMP_RAWKEY */
  435.        } /* txSig */
  436.      if (rxSig & erhaltSig)/* mind. 1 Zeich. im Empf-kanal*/
  437.        {
  438.         WaitIO(&rxRequest);             /* dieses abholen */
  439.         if (rxRequest.IOSer.io_Error == 0)
  440.            done = Write(rxWin, rxPuffer, 1);/*u. ausgeben */
  441.  
  442.         rxRequest.IOSer.io_Command = SDCMD_QUERY;
  443.         DoIO(&rxRequest);   /* noch mehr Zeichen im Kanal */
  444.         rxRequest.IOSer.io_Command = CMD_READ;
  445.         if (rxRequest.IOSer.io_Actual > 0)          /* ja */
  446.           {
  447.            rxRequest.IOSer.io_Length = /* auf Zeichenanz. */
  448.                                   rxRequest.IOSer.io_Actual;
  449.            DoIO(&(rxRequest));             /* alles lesen */
  450.            done =        /* und im Empf.-Fenst. darstell. */
  451.            Write(rxWin, rxPuffer,rxRequest.IOSer.io_Actual);
  452.            rxRequest.IOSer.io_Length = 1;
  453.           }
  454.  
  455.         SendIO(&rxRequest); /* aufs naechste Zeich. wart. */
  456.        }
  457.     } /* for */
  458.     AbortIO(&rxRequest);   /* Auftrag an Device abbrechen */
  459.     WaitIO(&rxRequest);
  460. }
  461.  
  462. void FlushSerialDevice()   /* extern geladenes Device aus */
  463. {                                    /* aus RAM entfernen */
  464. APTR serDev;
  465.  
  466.   serDev = (APTR)                  /* Serial-Dev. suchen */
  467.            FindName(&execBasePtr->DeviceList, SERIALNAME);
  468.   if (serDev)                                /* gefunden */
  469.     {
  470.      Forbid();               /* damit uns niemand stoert */
  471.      RemDevice(serDev);  /* belegte Ressourcen freigeben */
  472.      Permit();               /* wieder offen fuer andere */
  473.     }
  474. }
  475.  
  476. void Aufraeumen()
  477. {
  478.   DeleteMsgPort(rxRequest.IOSer.io_Message.mn_ReplyPort);
  479.   CloseDevice(&rxRequest);
  480.   DeleteMsgPort(txRequest.IOSer.io_Message.mn_ReplyPort);
  481.   CloseDevice(&txRequest);
  482.   Close(rxWin);
  483.   Close(txWin);
  484.   FlushSerialDevice();
  485. }
  486.  
  487. int main()
  488. {
  489.  BOOL done;
  490.  
  491.  execBasePtr = GetSysBase();   /* Adr ExecBase beschaffen */
  492.  
  493.  if (execBasePtr->LibNode.lib_Version >= 36) /* ja, OS 2  */
  494.   {
  495.    if (WindowsAngelegt() && SerialVorbereitet())
  496.      {
  497.       TerminalLoop();     /* Steuerschleife des Programms */
  498.       Aufraeumen();
  499.      }
  500.   }
  501.   return 0;
  502. }
  503.